/*
 *	Copyright 2011 andro-inject developers 
 *	Licensed under the Apache License, Version 2.0 (the "License"); 
 *	you may not use this file except in compliance with the License. 
 *	You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 * 
 *	Unless required by applicable law or agreed to in writing, software 
 *	distributed under the License is distributed on an "AS IS" BASIS,
 *	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *	See the License for the specific language governing permissions and
 *	limitations under the License. 
 * 
*/

package com.androinject.android.factory;

import java.io.InputStream;

import android.app.Application;

import com.androinject.android.aware.ApplicationAwareProcessor;
import com.androinject.android.factory.input.AndroidInputSource;
import com.androinject.core.factory.ComponentProcessor;
import com.androinject.core.factory.input.InputSource;
import com.androinject.core.factory.input.InputStreamInputSource;
import com.androinject.core.factory.xml.DefaultXmlComponentFactory;

/**
 * AndroidXmlComponentFactory is the default implementation of the ComponentFactory interface
 * that uses a xml component configuration for Android applications. <br />
 * When using Andro-Inject in Android application AndroidXmlComponentFactory should be used instead
 * of DefaultXmlComponentFactory. The xml component configuration file can be passed to 
 * AndroidXmlComponentFactory by using an Android resource id. AndroidXmlComponentFactory also supports
 * the ApplicationAware aware interface that can be implemented within components that required access to
 * the Android application object. <br />
 * This class depends on some Android platform classes so cannot be used outside of an Android environment.
 */
public class AndroidXmlComponentFactory extends DefaultXmlComponentFactory {
	
	private Application application;
	
	/**
	 * Creates a new AndroidXmlComponentFactory instance. Takes the Android application
	 * object and a resource id as parameter.
	 * @param application Android application object
	 * @param resId Android resource id that points to the xml component configuration file
	 */
	public AndroidXmlComponentFactory(Application application, int resId) {
		this(application, new AndroidInputSource(application, resId), null);
	}
	
	
	/**
	 * Creates a new AndroidXmlComponentFactory instance. Takes the Android application
	 * object and an InputStream as parameter. The InputStream is used to read the 
	 * component configuration.
	 * @param application Android application object
	 * @param inputStream InputStream from which the component configuration is read
	 */
	public AndroidXmlComponentFactory(Application application, InputStream inputStream) {
		this(application, new InputStreamInputSource(inputStream));
	}
	
	
	/**
	 * Creates a new AndroidXmlComponentFactory instance. Takes the Android application
	 * object and an InputSource as parameter. The InputSource is used to access the
	 * xml component configuration. Identical to calling AndroidXmlComponentFactory(application, inputSource, null).
	 * @param application Android application object
	 * @param inputSource InputSource that provides access to the component configuration.
	 */
	public AndroidXmlComponentFactory(Application application, InputSource inputSource) {
		this(application, inputSource, null);
	}
	
	
	/**
	 * Creates a new AndroidXmlComponentFactory instance. Takes the Android application 
	 * object, an InputSource and an array of custom component processors as parameter.
	 * The InputSource is used to access the xml component configuration.
	 * @param application Android application object
	 * @param inputSource InputSource that provides access to the component configuration
	 * @param componentProcessors Array of custom component processors that should be added to the factory
	 */
	public AndroidXmlComponentFactory(Application application, InputSource inputSource, ComponentProcessor[] componentProcessors) {
		this.application = application;
		this.inputSource = inputSource; // TODO +1 class knows about superclass internals
		this.setupComponentProcessors(componentProcessors);
		this.loadComponents();
	}
	
	
	@Override
	protected void setupComponentProcessors(ComponentProcessor[] componentProcessors) {
		super.setupComponentProcessors(componentProcessors);
		this.addComponentProcessor(new ApplicationAwareProcessor(this.application));
	}

}
